package sshexec

import (
	"context"
	"fmt"
	"io"
	"os/exec"
	"strconv"
	"strings"
)

type SSHCLIRemote struct {
	user    string
	host    string
	port    int
	keyPath string
}

func NewSSHCLIRemote(user, host string, port int, keyPath string) *SSHCLIRemote {
	return &SSHCLIRemote{
		user:    user,
		host:    host,
		port:    port,
		keyPath: keyPath,
	}
}

// TODO: Refactor and reuse this with buildDialArgs and buildSSHArgs from
// SSHCLI Connector.
func (r *SSHCLIRemote) buildSSHArgs() []string {
	args := []string{"-o", "ConnectTimeout=5"}

	if r.port != 0 && r.port != 22 {
		args = append(args, "-p", strconv.Itoa(r.port))
	}

	if r.keyPath != "" {
		args = append(args, "-i", r.keyPath)
	}

	args = append(args, r.user+"@"+r.host)
	return args
}

func (r *SSHCLIRemote) Run(ctx context.Context, cmd string) (string, error) {
	args := r.buildSSHArgs()
	args = append(args, cmd)

	execCmd := exec.CommandContext(ctx, "ssh", args...)
	output, err := execCmd.CombinedOutput()
	if err != nil {
		return strings.TrimSpace(string(output)),
			fmt.Errorf("run command on remote host: %w: %s", err, string(output))
	}
	return strings.TrimSpace(string(output)), nil
}

func (r *SSHCLIRemote) Stream(ctx context.Context, cmd string, stdout, stderr io.Writer) error {
	args := r.buildSSHArgs()
	args = append(args, cmd)

	execCmd := exec.CommandContext(ctx, "ssh", args...)
	execCmd.Stdout = stdout
	execCmd.Stderr = stderr

	return execCmd.Run()
}

// no-op as there is no persistent connection.
func (r *SSHCLIRemote) Close() error {
	return nil
}
